﻿// -----------------------------------------------------------------------
// <copyright file="K_mean.cs" company="">
// TODO: Update copyright text.
// </copyright>
// -----------------------------------------------------------------------

namespace Pattern_package.Classify_data
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Drawing;

    /// <summary>
    /// TODO: Update summary.
    /// </summary>
    public class K_mean
    {
        public struct Distance
        {
            public double dist;
            public int classNum;
        }
        private List<Color> colorOfEachClass;
        List<Distance> dist = new List<Distance>();
        private double[,] ValuesToClassfiy;
        private int NumberOfClass;
        private double[] OldCenteroid;
        List<double>[] classfeature;
        public void SetInfo(List<Color> colorOfEachClass, double[,] ValuesToClassfiy, int NumberOfClass, double[] OldCenteroid)
        {
            this.colorOfEachClass = colorOfEachClass;
            this.ValuesToClassfiy = ValuesToClassfiy;
            this.NumberOfClass = NumberOfClass;
            this.OldCenteroid = OldCenteroid;            
            this.classfeature = new List<double>[this.NumberOfClass];
            for (int k = 0; k < NumberOfClass; k++)
            {
                this.classfeature[k] = new List<double>();
            }
            this.Classify();
        }
        public Bitmap Classify()
        {
            Bitmap image;
            while (true)
            {
                this.classfeature = new List<double>[this.NumberOfClass];
                for (int k = 0; k < NumberOfClass; k++)
                {
                    this.classfeature[k] = new List<double>();
                }
                image = new Bitmap(ValuesToClassfiy.GetLength(0), ValuesToClassfiy.GetLength(1));
                for (int i = 0; i < this.ValuesToClassfiy.GetLength(0); i++)
                {
                    for (int j = 0; j < this.ValuesToClassfiy.GetLength(1); j++)
                    {
                        double Point = this.ValuesToClassfiy[i, j];
                        CalcDist(Point);
                        this.classfeature[this.dist[0].classNum].Add(Point);
                        Color c = this.colorOfEachClass[this.dist[0].classNum];
                        image.SetPixel(i, j, c);
                    }
                }
                int x = this.CalcNewCenter();
                if (x == 0)
                {
                    break;
                }                
            }
            return image;
        }
        public int CalcNewCenter()
        {
            int finish = 0;
            double[] NewCenteroid = new double[this.NumberOfClass];
            for (int i = 0; i < this.OldCenteroid.Length; i++)
            {
                double sum = 0;
                foreach (double d in this.classfeature[i])
                {
                    sum += d;
                }
                NewCenteroid[i] = sum / classfeature[i].Count;
                if (Math.Abs(NewCenteroid[i] - this.OldCenteroid[i]) < 0.1)
                {
                    finish++;
                }
            }
            if (finish == this.NumberOfClass)
            {
                return 0;
            }
            else
            {
                this.OldCenteroid = NewCenteroid;
                return 1;
            }
        }
        public void CalcDist(double Point)
        {
            this.dist.Clear();
            for (int i = 0; i < this.OldCenteroid.Length; i++)
            {
                Distance d = new Distance();
                d.classNum = i;
                d.dist = Math.Abs(Point-this.OldCenteroid[i]);
                this.dist.Add(d);
            }
            dist.Sort(delegate(Distance p1, Distance p2) { return p1.dist.CompareTo(p2.dist); });
            
        }
    }
}
